
#ifdef SYPX_MEMCHECK
#include "mmgr.h"
#endif

#include "WolfInstance.h"
#include "DogInstance.h"
#include "SheepInstance.h"
#include "Level.h"

namespace SheepDefence 
{
	SheepInstance::SheepInstance()
	{

	}

	SheepInstance::~SheepInstance()
	{
	}

	SheepInstance::SheepInstance(SypX::FileInputStream& fin, Sheep* actor, Level* level)
	{
		SypX::ErrorLogger::getLogger() << "Loading SheepInstance...\n";

		fin >> x;
		fin >> y;
		fin >> angle;
		dest_x = x;
		dest_y = y;

		SypX::ErrorLogger::getLogger() << "Loaded: " << x << ", " << y << ", " << angle << "\n";

		type = SHEEP;
		state = IDLE;
		stamState = NORMAL;
		pathState = OK;
		elapsed  = 0;
		this->level = level;
		this->actor = actor;
		hp = (float) actor->hp;
		stateAge = 0;
		
		sprite = new SypX::SpriteInstance();
		sprite->useSprite(actor->sprite);

		sprite->setPosition( SypX::Vec3(static_cast<float>(x), static_cast<float>(y), 0.2f) );		
		sprite->setActiveAngle(angle);

		level->numSheep++;
		SypX::ErrorLogger::getLogger()<<"SHEEP UP\n";
	}

	SheepInstance::SheepInstance(Sheep* actor, Level* level, float x, float y, int angle)
	{
		SypX::ErrorLogger::getLogger() << "Loading SheepInstance...\n";

		this->x = x;
		this->y = y;
		this->angle = angle;
		dest_x = x;
		dest_y = y;

		SypX::ErrorLogger::getLogger() << "Loaded: " << x << ", " << y << ", " << angle << "\n";

		type = SHEEP;
		state = IDLE;
		stamState = NORMAL;
		pathState = OK;
		elapsed  = 0;
		this->level = level;
		this->actor = actor;
		hp = (float) actor->hp;
		stateAge = 0;
		
		sprite = new SypX::SpriteInstance();
		sprite->useSprite(actor->sprite);

		sprite->setPosition( SypX::Vec3(static_cast<float>(x), static_cast<float>(y), 0.2f) );		
		sprite->setActiveAngle(angle);

		level->numSheep++;
		SypX::ErrorLogger::getLogger()<<"SHEEP UP\n";
	}

	void SheepInstance::act(float time)
	{
		stateAge += time;

		if (x > 310 || x < 10 || y > 470 || y < 10)
			if (state == RUNNING)
			{
				boundaryCheck(actor);
				return;
			}

		if (state == DEAD || state == BITTEN)
		{
			return;
		}

		if (state == TARGETED)
		{
			dest_x = x + x - pursuer->x;
			dest_y = y + y - pursuer->y;
			return;
		}

		if (state == STUCK)
		{
			changeState(IDLE);
			dest_x = x;
			dest_y = y;
			return;
		}

		if (state == FLEEING)
		{
			if (stateAge > 2)
			{
				changeState(IDLE);
				dest_x = x;
				dest_y = y;
			}
		}

		// IDLE, FLEEING or RUNNING

		std::vector<WolfInstance*>::iterator i = level->wolves.begin();	// Check wolf first, sheep more scared of wolf
		while (i != level->wolves.end())
		{
			if ((*i)->state != DEAD && getDist((*i), this) - actor->fear * actor->fear < 0)
			{
				dest_x = x + x - (*i)->x;
				dest_y = y + y - (*i)->y;

				// use fleeing texture
				if (state != TARGETED)
				{
					changeState(FLEEING);
				}

				return;
			}
			i++;
		}

		SypX::ErrorLogger::getLogger() << getDist(level->dog, this) << "\n";

		if (getDist(level->dog, this) - actor->fear * actor->fear < 0)
		{
			dest_x = x + x - level->dog->x;
			dest_y = y + y - level->dog->y;

			// use fleeing texture
			if (state != TARGETED)
			{
				changeState(FLEEING);
			}

			return;
		}
		
		if (state == IDLE)
		{
			if (stateAge > 2)
			{
				dest_x = x;
				dest_y = y;
			}

			float chance = 1 - (float) actor->rest / 100;
			chance = pow(chance, time);

			if (rand() % 10001 > chance * 10000)
			{
				dest_x = x + (rand() % 5 - 2) * actor->speed;
				dest_y = y + (rand() % 5 - 2) * actor->speed;

				// use walking/running texture
				changeState(RUNNING);
			}
		}
	}

	void SheepInstance::respond()
	{
		if (state == DEAD)
		{

			// use dead texture
			dest_x = x;
			dest_y = y;
			const SypX::Vec4& p = sprite->getPositionRef();
			sprite->setPosition(SypX::Vec3(p.x, p.y, 0.01f));
			sprite->setActiveAction("Dead");
			//sprite->transform[3].z = 0.01f;
			return;
		}

		if (state == BITTEN)
		{
			// use bitten texture
			dest_x = x;
			dest_y = y;
			return;
		}
	}

	bool SheepInstance::collide(Instance* target)
	{
		if (target == this || target->state == DEAD || target->state == BITTEN || target->state == BITING || target->state == POUNCING)
			return false;
		return true;
	}

	Actor* SheepInstance::getActor()
	{
		return actor;
	}
}